/*
 * @(#)BerichtGeneratorImpl.java
 * 1.0, 2013-01-24
 */
package de.hdm.gruppenkalender.team04.report;

import de.hdm.gruppenkalender.team04.GruppenkalenderVerwaltung;
import de.hdm.gruppenkalender.team04.data.Alarm;
import de.hdm.gruppenkalender.team04.data.Kalender;
import de.hdm.gruppenkalender.team04.data.Kategorie;
import de.hdm.gruppenkalender.team04.data.Person;
import de.hdm.gruppenkalender.team04.data.Termin;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Der Berichtgenerator dient zur Erzeugung von Berichten,
 * die aus einer Menge von Daten bestehen.
 * Es sind mehrere erstelle-Methoden implementiert,
 * bei denen anwendungsfallspezifische Parameterlisten vorliegen.
 * Beispielsweise kann ein Bericht von einer bestimmten Person ausgegeben werden,
 * oder aber Einträge gefiltert nach einer gewissen Kategorie
 *
 * @author Mathias Bendel (mb167)
 * @author Björn Fichnter (bf023)
 * @author Stefan Hettich (sh176)
 * @author René Kugel (rk044)
 * @author Mark Leonberger (ml072)
 * @author Marta Przybylski (mp070)
 *
 * @version 1.0, 2013-01-24
 *
 * @see BerichtGenerator
 *
 */
// <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
// #[regen=yes,id=DCE.7C1B310D-1AB2-0557-516A-B88460DCB47D]
// </editor-fold> 
public class BerichtGeneratorImpl extends UnicastRemoteObject
        implements BerichtGenerator {

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.3F9E77C2-5A66-8604-749F-AAF2C9C85A5B]
    // </editor-fold>
    private GruppenkalenderVerwaltung gruppenkalenderVerwaltung;

    /**
     * Konstruktor für den BerichtGeneratorImpl.
     *
     * @param   gruppenkalenderVerwaltung
     * @throws  java.rmi.RemoteException
     */
    public BerichtGeneratorImpl(
            GruppenkalenderVerwaltung gruppenkalenderVerwaltung) throws
            java.rmi.RemoteException {
        this.gruppenkalenderVerwaltung = gruppenkalenderVerwaltung;
    }

    /**
     * Erstellt den Bereicht, bei dem Person, Kategorie, Kalender, Start-
     * und Endzeitpunkt gefiltert werden.
     *
     * @param   person
     * @param   kategorie
     * @param   kalender
     * @param   von
     * @param   bis
     * @return  String          der HTML-Report beinhaltet.
     * @throws  RemoteException
     */
    public String erstelleReport(Person person, Kalender kalender,
            Kategorie kategorie, Timestamp von, Timestamp bis) throws
            RemoteException {

        Vector<Termin> termine = this.gruppenkalenderVerwaltung.
                ermittleAlleTerminVia(person, kalender, kategorie, von, bis);
        Vector<Alarm> alarme = this.gruppenkalenderVerwaltung.
                ermittleAlleAlarmeVia(person, kalender, kategorie, von, bis);

        StringBuffer sb = new StringBuffer();

        sb.append("<html>\n");
        sb.append("<body>\n");

        // Person
        String personString = "alle Personen";
        if (person != null) {
            personString = person.getVorname() + " " + person.getNachname();
        }
        sb.append("<h1>Report für: " + personString + "</h1>\n");
        sb.append("<p>");

        // Zeitraum
        String zeitraumString = "gesamter Zeitraum";
        if (von != null && bis == null) {
            zeitraumString = "ab " + datumZuString(von, bis, false);
        } else if (bis != null && von == null) {
            zeitraumString = "bis " + datumZuString(von, bis, false);
        } else if (bis != null && von != null) {
            zeitraumString = datumZuString(von, bis, false);
        }
        sb.append("<strong>Zeitraum:</strong> " + zeitraumString + " ");
        // Kalender
        String kalenderString = "alle Kalender";
        if (kalender != null) {
            kalenderString = kalender.getBezeichnung();
        }
        sb.append("<strong>Kalender:</strong> " + kalenderString + " ");
        // Kategorie
        String kategorieString = "alle Kategorien";
        if (kategorie != null) {
            kategorieString = kategorie.getName();
        }
        sb.append("<strong>Kategorie:</strong> " + kategorieString);
        sb.append("</p>\n");

        sb.append("<p>&nbsp;</p>");

        sb.append("<h2>Termine</h2>\n");
        sb.append("<table border='1'>\n");
        sb.append("<tr>\n");
        sb.append("<th>Datum</th>\n");
        sb.append("<th>Titel</th>\n");
        sb.append("<th>Ort</th>\n");
        sb.append("<th>Beschreibung</th>\n");
        sb.append("<th>Kategorie</th>\n");
        sb.append("<th>Ersteller</th>\n");
        sb.append("<th>Kalender</th>\n");
        sb.append("<th>Teilnehmer</th>\n");
        sb.append("<th>Wiederholung</th>\n");
        sb.append("</tr>\n");

        if (termine.size() == 0) {
            sb.append("<td colspan='9'><i>Keine Termine vorhanden.</i></td>");
        }
        for (Termin termin : termine) {
            sb.append(terminZuHTML(termin));
        }

        sb.append("</table>\n");

        sb.append("<p>&nbsp;</p>");

        sb.append("<h2>Alarme</h2>\n");

        sb.append("<table border='1'>\n");
        sb.append("<tr>\n");
        sb.append("<th>Datum</th>\n");
        sb.append("<th>Titel</th>\n");
        sb.append("<th>Kategorie</th>\n");
        sb.append("<th>Ersteller</th>\n");
        sb.append("<th>Kalender</th>\n");
        sb.append("</tr>\n");

        if (alarme.size() == 0) {
            sb.append("<td colspan='5'><i>Keine Alarme vorhanden.</i></td>");
        }
        for (Alarm alarm : alarme) {
            sb.append(AlarmZuHTML(alarm));
        }

        sb.append("</table>\n");

        sb.append("</body>\n");
        sb.append("</html>\n");

        return sb.toString();
    }

    /**
     * Gibt einen Termin als HTML-Tabellenzeile aus.
     *
     * @param   termin
     * @return  String  mit Termin als HTML-Tabellenzeile.
     */
    private String terminZuHTML(Termin termin) {
        StringBuffer sb = new StringBuffer();

        sb.append("<tr>\n");
        try {
            // Start- und Endatum.
            sb.append("<td>" + datumZuString(termin.getStart(),
                    termin.getEnde(), true) + "</td>\n");
            // Titel
            sb.append("<td>" + termin.getTitel() + "</td>\n");
            // Ort
            sb.append("<td>" + termin.getOrt() + "</td>\n");
            // Beschreibung
            sb.append("<td>" + termin.getBeschreibung() + "</td>\n");
            // Kategorie
            Kategorie kategorie = gruppenkalenderVerwaltung.
                    ermittleKategorieViaSchluessel(termin.getKategorieId());
            sb.append("<td>" + kategorie.getName() + "</td>\n");
            // Person
            Person person = gruppenkalenderVerwaltung.
                    ermittlePersonViaSchluessel(termin.getErstellerId());
            sb.append("<td>" + person.getVorname() + " " +
                    person.getNachname() + "</td>\n");
            // Kalender
            Kalender kalender = gruppenkalenderVerwaltung.
                    ermittleKalenderViaSchluessel(termin.getKalenderId());
            sb.append("<td>" + kalender.getBezeichnung() + "</td>\n");
            // Teilnehmer
            String teilnehmerString = "";
            for (int p : termin.getTeilnehmerIds()) {
                Person teilnehmer = gruppenkalenderVerwaltung.
                        ermittlePersonViaSchluessel(p);
                teilnehmerString += (teilnehmer.getNachname() + ", ");
            }
            teilnehmerString = teilnehmerString.substring(0, teilnehmerString.
                    length() - 2);
            sb.append("<td>" + teilnehmerString + "</td>\n");
            // Wiederholung
            String wiederholungString = "";
            if (gruppenkalenderVerwaltung.istWiederholung(termin.getId())) {
                wiederholungString = "W";
            } else {
                wiederholungString = "T";
            }
            sb.append("<td>" + wiederholungString + "</td>\n");
        } catch (RemoteException ex) {
            Logger.getLogger(BerichtGeneratorImpl.class.getName()).
                    log(Level.SEVERE, null, ex);
        }

        sb.append("</tr>\n");

        return sb.toString();
    }

    /**
     * Gibt einen Alarm als HTML-Tabellenzeile aus.
     *
     * @param   alarm
     * @return  String mit Alarm als HTML-Tabellenzeile.
     */
    private String AlarmZuHTML(Alarm alarm) {
        StringBuffer sb = new StringBuffer();

        sb.append("<tr>\n");
        try {
            // Start- und Endatum.
            sb.append("<td>" + datumZuString(alarm.getStart(), null, true) +
                    "</td>\n");
            // Titel
            sb.append("<td>" + alarm.getTitel() + "</td>\n");
            // Kategorie
            Kategorie kategorie = gruppenkalenderVerwaltung.
                    ermittleKategorieViaSchluessel(alarm.getKategorieId());
            sb.append("<td>" + kategorie.getName() + "</td>\n");
            // Person
            Person person = gruppenkalenderVerwaltung.
                    ermittlePersonViaSchluessel(alarm.getErstellerId());
            sb.append("<td>" + person.getVorname() + " " +
                    person.getNachname() + "</td>\n");
            // Kalender
            Kalender kalender = gruppenkalenderVerwaltung.
                    ermittleKalenderViaSchluessel(alarm.getKalenderId());
            sb.append("<td>" + kalender.getBezeichnung() + "</td>\n");
        } catch (RemoteException ex) {
            Logger.getLogger(BerichtGeneratorImpl.class.getName()).
                    log(Level.SEVERE, null, ex);
        }

        sb.append("</tr>\n");

        return sb.toString();
    }

    /**
     * Wandelt Start- und Enddatum in einen String um.
     * 
     * @param   start
     * @param   ende
     * @return  String  Start- und Enddatum als String
     */
    private String datumZuString(Timestamp start, Timestamp ende,
            boolean mitUhrzeit) {
        SimpleDateFormat dateFormat;
        if (mitUhrzeit) {
            dateFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm");
        } else {
            dateFormat = new SimpleDateFormat("dd.MM.yyyy");
        }

        /**
         * Wenn Enddatum leer ist, nur das Startdatum ausgeben.
         */
        if (ende == null) {
            return dateFormat.format(start);
        }
        if (start == null) {
            return dateFormat.format(ende);
        }
        return dateFormat.format(start) + " - " + dateFormat.format(ende);
    }
}
